import { IScene, IView, TipsType } from "../../app_base/module/view/IView";
import { ViewConfig } from "../../app_base/module/view/IViewLoader";
import { app } from "../../base";
import { TipsView } from "../../ui/tips/TipsView";
import { CCPViewLoader } from "./CCPViewLoader";
import { View } from "./View";
import { ViewControl } from "./ViewControl";


export enum ViewLevel {
    TOPUP = 500,
    NET = 400,
    TUTORIAL = 300,
    ALERT = 200,
    UI = 100,
    BG = 1,
}

/**
 * cocos环境下ViewManager所持有的root
 */
const { ccclass, property, menu } = cc._decorator;

@ccclass()
@menu("基础视图/Scene")
export class Scene extends View implements IScene {
    @property(cc.String)
    sceneName: string = "";

    protected _control: ViewControl;
    private _tipsViewLoader: CCPViewLoader;

    public setControl(control: ViewControl): void {
        if (!this._control) {
            this.name = this.sceneName;
            app.viewManager.setRoot(this);
            this.bundle = cc.assetManager.bundles.find((value, key) => {
                return value.getSceneInfo(this.sceneName) != null
            });
            console.log("Scene setControl", this.sceneName, this.bundle);
            this._control = control;
        }
    }

    public addView(view: View, index?: number): void {
        super.addView(view, index);
        view.touchEnabled = true;
    }

    /**
     * 已启用，建议使用this._control.addView\this._control.addViewTo
     * 添加视图到当前主视图
     * 根据视图的cache配置对视图进行缓存，再此显示对应视图时，复用之前缓存的视图。
     * Scene被销毁时，所有缓存视图随之销毁。
     * @deprecated
     * @param config 
     * @param parent 目标父级视图，默认添加到app.viewManager.view()
     * @param data 
     */
    public async addViewTo<T extends IView>(config: ViewConfig, parent: View, ...data: any[]): Promise<T> {
        const view: IView = await app.viewManager.addView<T>(config, parent, ...data);
        return view as T;
    }

    /**
     * 已启用，建议使用this._control.switchView
     * 将主视图切换到目标视图，并移除之前主视图。
     * 根据视图的cache配置对视图进行缓存，再此显示对应视图时，复用之前缓存的视图。
     * Scene被销毁时，所有缓存视图随之销毁。
     * 使用注意：每个类型的视图在缓存中只缓存最新的视图实例。
     * @deprecated
     * @param config 
     * @param data 
     */
    public async switchView<T extends IView>(config: ViewConfig, ...data: any[]): Promise<T> {
        return await app.viewManager.switchTo<T>(config, ...data);
    }

    /**
     * 已弃用，请调用app.viewManager.switchBack.
     * 切回当前主视图到上一个主视图。
     * @deprecated
     * @param data 
     * @returns 
     */
    public async switchBack<T extends IView>(...data: any[]): Promise<T> {
        return await app.viewManager.switchBack(...data);
    }

    /**
     * 显示正常提示
     * @param message 提示文本内容
     */
    public tips(message: string): void {
        this._tips(message, TipsType.normal);
    }

    /**
     * 显示警告提示
     * @param message 警告文本内容
     */
    public warn(message: string): void {
        this._tips(message, TipsType.warn);
    }

    /**
     * 显示错误提示
     * @param message 错误文本内容
     */
    public error(message: string): void {
        this._tips(message, TipsType.error);
    }

    protected async _tips(tipContent: string, type: TipsType) {
        if (!this._tipsViewLoader) {
            this._tipsViewLoader = await app.viewManager.loadView("TipsView") as CCPViewLoader;
        }
        let tipsView: TipsView = app.viewManager.getCacheView("TipsView") || this._tipsViewLoader.initView(TipsType[type], false);
        tipsView.setData(tipContent, type);
        tipsView.popup();
        app.viewManager.cacheView(tipsView);
    }

    protected onDestroy(): void {
        this._tipsViewLoader && this._tipsViewLoader.destroy();
        this._tipsViewLoader = null;
        this._control && this._control.offAllEvent();
        this._control = null;
    }

    public addToTopup(view: View) {
        this.addView(view, ViewLevel.TOPUP);
    }

    public addToNet(view: View) {
        this.addView(view, ViewLevel.NET);
    }

    public addToTutorial(view: View) {
        this.addView(view, ViewLevel.TUTORIAL);
    }

    public addToAlert(view: View) {
        this.addView(view, ViewLevel.ALERT);
    }

    public addToUI(view: View) {
        this.addView(view, ViewLevel.UI);
    }

    public addToBG(view: View) {
        this.addView(view, ViewLevel.BG);
    }
}
